package itsm.isperp.module.controller.api.wechat;

import itsm.isperp.framework.core.context.ContextHolder;
import itsm.isperp.framework.domain.IUser;
import itsm.isperp.framework.domain.UploadInfo;
import itsm.isperp.framework.service.UploadFileService;
import itsm.isperp.framework.template.Template;
import itsm.isperp.framework.utils.DateUtils;
import itsm.isperp.framework.utils.FileUploadUtils;
import itsm.isperp.module.dto.app.ChatMessage;
import itsm.isperp.module.entity.app.AppUser;
import itsm.isperp.module.entity.wechat.WechatChat;
import itsm.isperp.module.entity.wechat.WechatNewsArticle;
import itsm.isperp.module.entity.wechat.mp.WechatMpMenu;
import itsm.isperp.module.service.app.AppUserService;
import itsm.isperp.module.service.wechat.WechatChatService;
import itsm.isperp.module.service.wechat.WechatNewsArticleService;
import itsm.isperp.module.service.wechat.mp.WechatMpMenuService;
import itsm.isperp.module.utils.WechatConfigUtils;

import java.io.File;
import java.io.IOException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.exception.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpConfigStorage;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.WxMpXmlMessage;
import me.chanjar.weixin.mp.bean.WxMpXmlOutMessage;
import me.chanjar.weixin.mp.bean.WxMpXmlOutNewsMessage;
import me.chanjar.weixin.mp.bean.WxMpXmlOutNewsMessage.Item;
import me.chanjar.weixin.mp.bean.WxMpXmlOutTextMessage;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.messaging.simp.SimpMessagingTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * 微信
 * 
 * @author zhouhg
 * @date 2014-3-11
 * @version V1.0
 */
@Controller
@RequestMapping("api/wechat/mp")
public class WechatMpController {

	public static final Logger logger = LoggerFactory
			.getLogger(WechatMpController.class);

	@Autowired
	SimpMessagingTemplate simpMessagingTemplate;

	@Autowired
	WxMpService wxMpService;

	// 处理微信用户的请求
	@RequestMapping(value = "/main")
	public void weixinInterfacePost(HttpServletResponse response,
			HttpServletRequest request) throws Exception {

		response.setContentType("text/html;charset=utf-8");
		response.setStatus(HttpServletResponse.SC_OK);

		String signature = request.getParameter("signature");
		String nonce = request.getParameter("nonce");
		String timestamp = request.getParameter("timestamp");

		if (!wxMpService.checkSignature(timestamp, nonce, signature)) {
			// 消息签名不正确，说明不是公众平台发过来的消息
			response.getWriter().println("非法请求");
			return;
		}

		String echostr = request.getParameter("echostr");
		if (StringUtils.isNotBlank(echostr)) {
			// 说明是一个仅仅用来验证的请求，回显echostr
			response.getWriter().println(echostr);
			return;
		}

		String encryptType = StringUtils.isBlank(request
				.getParameter("encrypt_type")) ? "raw" : request
				.getParameter("encrypt_type");

		if ("raw".equals(encryptType)) {
			// 明文传输的消息
			WxMpXmlMessage inMessage = WxMpXmlMessage.fromXml(request
					.getInputStream());

			WxMpXmlOutMessage outMessage = this.service(inMessage);
			if (outMessage != null) {
				response.getWriter().write(outMessage.toXml());
			}
			return;
		}

		if ("aes".equals(encryptType)) {
			// 是aes加密的消息
			WxMpConfigStorage wxMpConfigStorage = ContextHolder.getWxMpConfig();
			String msgSignature = request.getParameter("msg_signature");
			WxMpXmlMessage inMessage = WxMpXmlMessage.fromEncryptedXml(
					request.getInputStream(), wxMpConfigStorage, timestamp,
					nonce, msgSignature);

			WxMpXmlOutMessage outMessage = this.service(inMessage);
			if (outMessage != null) {
				response.getWriter().write(
						outMessage.toEncryptedXml(wxMpConfigStorage));
			}
			return;
		}

		response.getWriter().println("不可识别的加密类型");
		return;
	}

	private void sendChat(WxMpXmlMessage xml, String data, IUser user) {

		ChatMessage message = new ChatMessage();

		message.setSuccess(true);
		message.setOpenid(xml.getFromUserName());
		message.setMsgType(xml.getMsgType());
		message.setSenderName(user.getFullname());
		message.setSendTime(DateUtils.DF_LONG_LONG.format(xml.getCreateTime()));
		message.setData(data);

		WechatChat c = new WechatChat();
		c.setOpenid(message.getOpenid());
		c.setSendContent(message.getData());
		c.setMsgType(message.getMsgType());
		c.setSenderName(message.getSenderName());
		c.setSendFrom(message.getSender());
		c.setSendTime(new Timestamp(new Date().getTime()));

		WechatChatService wechatChatService = ContextHolder
				.getSpringBean("wechatChatService");
		wechatChatService.saveOrUpdate(c);

		simpMessagingTemplate.convertAndSend("/chatMessage/result", message);
	}

	private WxMpXmlOutMessage service(WxMpXmlMessage xml) {

		boolean isWorktime = WechatConfigUtils.isWechatWorktime();

		WxMpXmlOutMessage outMessage = null;

		if (!WxConsts.XML_MSG_EVENT.equals(xml.getMsgType()) && !isWorktime) {

			outMessage = generalTxtMessage(xml,
					ContextHolder.getConfigByKey("wechatMpNoworkTimeNotice"));
			return outMessage;
		}
		AppUserService appUserService = ContextHolder
				.getSpringBean("appUserService");
		AppUser user = appUserService.findByOpenid(xml.getFromUserName());

		switch (xml.getMsgType()) {
		case WxConsts.XML_MSG_EVENT:
			WechatMpMenuService wechatMpMenuService = ContextHolder
					.getSpringBean("wechatMpMenuService");

			WechatMpMenu menu = wechatMpMenuService.findOneByKey(xml
					.getEventKey());

			if (menu.getNeedAccount()) {

				if (user == null) {

					outMessage = generalTxtMessage(xml,
							ContextHolder
									.getConfigByKey("wechatMpRegisterNotice"));

					return outMessage;
				} else if (!user.isEnable()) {
					outMessage = generalTxtMessage(
							xml,
							ContextHolder
									.getConfigByKey("wechatMpRegisterApprovalNotice"));

					return outMessage;

				}
			}

			String replayType = menu.getReplayType();

			switch (replayType) {
			case "text":
				outMessage = generalTxtMessage(xml, menu.getMessageContent());
				break;

			case "news":
				outMessage = generalNewsMessage(xml, menu.getNewsId());

				break;
			}

			break;
		case WxConsts.XML_MSG_TEXT:

			sendChat(xml, xml.getContent(), user);
			break;
		case WxConsts.XML_MSG_IMAGE:
		case WxConsts.XML_MSG_VOICE:

			File file = null;
			try {
				file = wxMpService.mediaDownload(xml.getMediaId());
			} catch (WxErrorException e1) {
				outMessage = generalTxtMessage(xml, "您发送到服务器的文件无法接收！");
			}

			String msgTypeName = "";
			UploadInfo uploadInfo = null;
			String fileNameExt = "";
			if (WxConsts.XML_MSG_IMAGE.equals(xml.getMsgType())) {
				msgTypeName = "图片";
				fileNameExt = "png";

			} else if (WxConsts.XML_MSG_VOICE.equals(xml.getMsgType())) {
				msgTypeName = "语音";
				fileNameExt = "amr";

			} else if (WxConsts.XML_MSG_VIDEO.equals(xml.getMsgType())) {
				msgTypeName = "视频";
				fileNameExt = "mp4";

			}

			try {
				uploadInfo = FileUploadUtils.persist(file, fileNameExt,
						msgTypeName);

				uploadInfo.setMeno(xml.getMediaId());
				UploadFileService<UploadInfo> uploadFileService = ContextHolder
						.getSpringBean("appUploadFileService");

				uploadFileService.saveOrUpdate(uploadInfo);

			} catch (IOException e) {
				logger.error(e.getMessage(), e);

				outMessage = generalTxtMessage(xml, "您发送到服务器的文件无法保存！");

			}

			sendChat(xml, uploadInfo.getPath(), user);

			break;
		default:
			outMessage = generalTxtMessage(xml, "不支持此类型操作，请返回菜单！");

			break;
		}

		return outMessage;
	}

	private WxMpXmlOutTextMessage generalTxtMessage(WxMpXmlMessage xml,
			String text) {
		WxMpXmlOutTextMessage out = new WxMpXmlOutTextMessage();
		// 在配置中取得信息
		Map<String, Object> vars = new HashMap<String, Object>();
		final String url = ContextHolder.getWebServerName();
		vars.put("config", ContextHolder.CONFIG_RESOURCES_MAP);
		vars.put("openid", xml.getFromUserName());
		vars.put("contextUrl", url);

		Template template = new Template(text);
		template.setContext(vars);

		try {
			out.setContent(template.render());
		} catch (Exception e) {

			out.setContent("服务器错误！");
		}
		out.setFromUserName(xml.getToUserName());
		out.setToUserName(xml.getFromUserName());
		out.setCreateTime(new Date().getTime());
		return out;
	}

	public static WxMpXmlOutNewsMessage generalNewsMessage(WxMpXmlMessage msg,
			String newsId) {
		WxMpXmlOutNewsMessage message = new WxMpXmlOutNewsMessage();
		message.setFromUserName(msg.getToUserName());
		message.setToUserName(msg.getFromUserName());
		message.setCreateTime(new Date().getTime());
		final String url = ContextHolder.getWebServerName();
		WechatNewsArticleService wechatNewsArticleService = ContextHolder
				.getSpringBean("wechatNewsArticleService");
		List<WechatNewsArticle> articles = null;
		try {

		  String openId=msg.getFromUserName();
			articles = wechatNewsArticleService.findByNewsId(newsId,openId);

		} catch (Exception e) {
			articles = new ArrayList<>();
			WechatNewsArticle article = new WechatNewsArticle();
			article.setTitle("谢谢关注!");

			articles.add(article);
		}
		Map<String, Object> vars = new HashMap<String, Object>();
		vars.put("config", ContextHolder.CONFIG_RESOURCES_MAP);
		vars.put("openid", msg.getFromUserName());
		vars.put("contextUrl", url);

		for (WechatNewsArticle article : articles) {
			Item item = new Item();
			item.setDescription(article.getDescription());
			item.setPicUrl(url + article.getPicurl());
			item.setTitle(article.getTitle());

			try {
				Template template = new Template(article.getUrl());
				template.setContext(vars);

				item.setUrl(template.render());
			} catch (Exception e) {
				item.setUrl(url + article.getUrl());

			}

			message.addArticle(item);
		}

		// 在配置中取得信息

		return message;

	}
}
